<?php
/**
 *	KLF Framework
 *
 *	Written by Kristian Oye <kristianoye@gmail.com> on Oct 23, 2011
 *	Copyright (C) 2010-2011
 */
namespace KLF\System\Web
{
	use KLF\System\KObject;

	/**
	 *  Class KUrl
	 *
	 *  @package KLF\System\Web
	 *  @access public
	 *  @author Kristian Oye <kristianoye@gmail.com>
	 *  @since 0.1
	 *  
	 *  @method KUrl NewInstance
	 *  
	 *  @property string $AbsoluteUri The absolute HTTP URI.
	 *  @property string $Host The hostname of the HTTP host.
	 *  @property bool $IsDefaultPort The request came via the default HTTP port.
	 *  @property bool $IsLoopback The request came in on the loop back interface.
	 *  @property string $OriginalString The original URL string.
	 *  @property string $PathAndQuery The URI plus the request string.
	 *  @property int $Port The TCP/IP port number.
	 *  @property string $Query The query string.
	 *  @property string $Scheme The HTTP protocol scheme.
	 *  @property array $Segments The URL path segments
	 *  @property int $StandardPort The default standard port.
	 */
	class KUrl extends KObject
	{
		/**
		 * The absolute URI of the request.
		 * 
		 * @var string
		 */
		protected $_propAbsoluteUri;
		
		/**
		 * The hostname being requested in the request.
		 * 
		 * @var string
		 */
		protected $_propHost;
		
		/**
		 * True if the request is on the default port.
		 * 
		 * @var bool
		 */
		protected $_propIsDefaultPort;
		
		/**
		 * True if the request comes over the loopback device.
		 * 
		 * @var bool
		 */
		protected $_propIsLoopback;
		
		/**
		 * The local path string
		 * 
		 * @var string
		 */
		protected $_propLocalPath;
		
		/**
		 * The original full string
		 * 
		 * @var string
		 */
		protected $_propOriginalString;
		
		/**
		 * The path and query string
		 * 
		 * @var string
		 */
		protected $_propPathAndQuery;
		
		/**
		 * The port number
		 * 
		 * @var int $_propPort
		 */
		protected $_propPort;
		
		/**
		 * The HTTP query string
		 * 
		 * @var string
		 */
		protected $_propQuery;
		
		/**
		 * The URL protocol scheme.
		 * 
		 * @var string $_propScheme
		 */
		protected $_propScheme;
		
		/**
		 * The URL segment parts.
		 * 
		 * @var array $_propSegments
		 */
		protected $_propSegments;
		
		/**
		 * Standard port number
		 * 
		 * @var int
		 */
		protected $_propStandardPort;
		
		
		/**
		 * Creates a KUrl object from the request being dispatched.
		 * 
		 * @return KUrl
		 */
		public static function GetCurrentUrl()
		{
			global $_SERVER;
			$parts = array();
			$portCheck = 80;
			
			if (strpos($_SERVER['SERVER_PROTOCOL'], 'HTTPS') === 0)
			{
				array_push($parts, 'https://');
				$portCheck = 443;
			}
			else
			{
				array_push($parts, 'http://');
				$portCheck = 80;
			}
			array_push($parts, $_SERVER["SERVER_NAME"]);
			
			// Check for new standard port
			if(isset($_SERVER['SERVER_PORT']) && $_SERVER['SERVER_PORT'] != $portCheck)
			{
				array_push($parts, ':'.$_SERVER['SERVER_PORT']);
			} 
			if(isset($_SERVER['REQUEST_URI']))
			{
				array_push($parts, $_SERVER['REQUEST_URI']);
			}
			return new KUrl(implode('', $parts));
		}
		
		
		/**
		 * Returns a well-known port for the given scheme.
		 * 
		 * @param $scheme
		 * @return int
		 */
		public static function GetSchemePort($scheme='http')
		{
			switch($scheme)
			{
				case 'ftp': return 23;
				case 'http': return 80;
				case 'https': return 443;
			}
		}
		
		
		/**
		 * Constructs a new KUrl object
		 */
		public function __construct($url)
		{
			$matches = array();
			$this->_propOriginalString = $url;
			
			if (preg_match("/^(?<scheme>[^:]+)+:\/\/(?<host>[^:\/]+)+([:]*(?<port>\d+))*(?<localPath>[^\?]+)(?<query>\?.+)*/", 
				$this->_propOriginalString, $matches))
			{
				$this->_propHost = $matches['host'];
				$this->_propScheme = $matches['scheme'];
				$this->_propIsLoopback = ($this->_propHost === 'localhost' || $this->_propHost === '127.0.0.1');
				$this->_propLocalPath = $this->_propAbsoluteUri = $matches['localPath'];
				$this->_propPort = isset($matches['port']) ? $matches['port'] : KUrl::GetSchemePort($this->_propScheme);
				$this->_propQuery = isset($matches['query']) ? $matches['query'] : '';
				$this->_propPathAndQuery = $this->_propLocalPath . $this->_propQuery;
				$this->_propSegments = array_values(array_filter(preg_split('/([^\/]*[\/]{1})/', 
						$this->_propLocalPath, 
						-1, 
						\PREG_SPLIT_DELIM_CAPTURE), function($x) { return strlen($x) > 0; }));
				$this->_propStandardPort = KUrl::getSchemePort($this->_propScheme);
				$this->_propIsDefaultPort = ($this->_propPort == $this->_propStandardPort);
			}
		}
		
		/**
		 * Returns the segments of the URL
		 *
		 * @author Kristian Oye <kristianoye@gmail.com>
		 * @since 0.1
		 * @return array The URL segments
		*/
		public function getSegments()
		{
			return $this->_propSegments;
		}
	}
}
